home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v7n16.arc / MAKEBAS.ASM < prev    next >
Assembly Source File  |  1988-09-13  |  41KB  |  777 lines

  1.                 PAGE    59,132
  2.                 TITLE   MAKEBAS - Create .BAS source to recreate a file
  3. ;----------------------------------------------------------------------
  4. ; MAKEBAS.ASM
  5. ;
  6. ; Author..: Salvatore P. Ricciardi
  7. ; Version.: 01.00
  8. ;
  9. ; Creates .BAS files to use when creating the PC Magazine utilities.
  10. ;----------------------------------------------------------------------
  11.                 page
  12. ;----------------------------------------------------------------------
  13. ;--- EQUATES, RECORDS and STRUCTURES
  14. ;----------------------------------------------------------------------
  15. LF              EQU     0AH                     ;line feed
  16. CR              EQU     0DH                     ;carriage return
  17. BYTES_LINE      EQU     16D                     ;bytes per line of data
  18. LINE_INCR       EQU     10D                     ;line number increment
  19. LASTBASIC       EQU     260D                    ;last basic statement
  20.                                                 ;before data statements
  21. STACKSAVE       EQU     200D                    ;stack requirement
  22.  
  23. ;----------------------------------------------------------------------
  24. ;--- CODE
  25. ;----------------------------------------------------------------------
  26. CSEG            SEGMENT PARA PUBLIC 'CODE'
  27.                 ASSUME  CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  28.  
  29.                 ORG     100h                    ;Starting offset for .COM files
  30. ENTRY:          JMP     START                   ;Jump to start
  31.  
  32. COPYRIGHT       DB      "MAKEBAS 1.0 (C) 1988 Ziff Communications Co.",CR,LF
  33.                 DB      "PC Magazine ",254," Salvatore P. Ricciardi",CR,LF
  34.                 DB      CR,LF,"$"
  35. USAGE           DB      "Usage: MAKEBAS [d:][\path\]filename[.ext]",CR,LF,"$"
  36.                 DB      1AH
  37. BASIC_CODE      DB      "100 REM - BASIC PROGRAM TO CREATE "
  38. FLNAME          DB      12 DUP(" "),CR,LF
  39.                 DB      "110 CLS:PRINT ""Creating "
  40. FLNAME0         DB      12 DUP(" ")
  41.                 DB      """: OPEN """
  42. FLNAME1         DB      12 DUP(" ")
  43.                 DB      """ AS #1 LEN = 1",CR,LF
  44.                 DB      "120 FIELD #1, 1 AS A$: CHECKSUM#=0",CR,LF
  45.                 DB      "130 FOR I = 1 TO "
  46. LINECOUNT       DB      5 DUP(" "),CR,LF
  47.                 DB      "140  LINESUM#=0: LOCATE 2,3: "
  48.                 DB      "PRINT ""Countdown: "" "
  49. COUNTDOWN       DB      5 DUP(" ")," - I ;",CR,LF
  50.                 DB      "150  FOR J = 1 TO "
  51. B_PER_LINE      DB      3 DUP(" "),": READ BYTE$: "
  52.                 DB      "CHECKSUM#=CHECKSUM#+VAL(""&H""+BYTE$)"
  53.                 DB      CR,LF
  54.                 DB      "160   LINESUM#=LINESUM#+VAL(""&H""+BYTE$)",CR,LF
  55.                 DB      "170   IF (BYTE < 256) THEN LSET A$=CHR$"
  56.                 DB      "(VAL(""&H""+BYTE$)): PUT #1",CR,LF
  57.                 DB      "180  NEXT J",CR,LF
  58.                 DB      "190  READ LINETOT$: LINECHECK# = VAL(""&H""+LINETOT$)"
  59.                 DB      CR,LF
  60.                 DB      "200  IF LINECHECK# = LINESUM# THEN GOTO 220",CR,LF
  61.                 DB      "210  LOCATE 4,2: PRINT ""Error in line #""  ;"
  62. ALASTBAS        DB      5 DUP(" ")," + "
  63. AINCR           DB      3 DUP(" ")," * I: GOTO 260",CR,LF
  64.                 DB      "220 NEXT I",CR,LF
  65.                 DB      "230 CLOSE: READ FILETOT$ : FILECHECK# = VAL(FILETOT$)"
  66.                 DB      CR,LF
  67.                 DB      "240 IF CHECKSUM# <> FILECHECK# THEN GOTO 260",CR,LF
  68.                 DB      "250 PRINT: PRINT """
  69. FLNAME2         DB      12 DUP(" ")
  70.                 DB      " created successfully"": SYSTEM",CR,LF
  71.                 DB      "260 PRINT: PRINT """
  72. FLNAME3         DB      12 DUP(" ")
  73.                 DB      " is not valid!"": END",CR,LF
  74. BASICLEN        EQU     $-BASIC_CODE            ;sum length of basic lines
  75.  
  76. BASICDATA       DB      5 DUP(" ")              ;space for the line number
  77.                 DB      " DATA "                ;these are DATA statements
  78. BBUFFER         DB      ((BYTES_LINE*4)+7) DUP(" ")
  79. BASICDATAL      EQU     $-BASICDATA             ;Length for the write
  80.  
  81. ERRORLVL        DB      0                       ;Return code
  82. FNSTART         DW      0                       ;offset of filename on cmdline
  83. LINENUMBER      DW      0                       ;line number
  84.  
  85. SRCFILE         DB      ".COM",0                ;default file extent
  86. SRCFLEN         EQU     $-SRCFILE               ;length for mov
  87. SRCHANDLE       DW      ?                       ;file handle when opened
  88.  
  89. BASFILE         DB      ".BAS",0                ;file extent for BAS file
  90. BASFLEN         EQU     $-BASFILE               ;length for mov
  91. BASHANDLE       DW      0                       ;file handle when opened
  92.  
  93. EXISTSMSG       DB      ".BAS file"             ;message when file exists
  94.                 DB      " already exists. Overwrite (y/n)? :","$"
  95. LINERROR        DB      "MAKEBAS: Error, line number too big",CR,LF,"$"
  96. SRCERROR        DB      "MAKEBAS: Source file error",CR,LF,"$"
  97. BASERROR        DB      "MAKEBAS: .BAS file error",CR,LF,"$"
  98. NOMEMORY        DB      "MAKEBAS: Not enough memory",CR,LF,"$"
  99. WORKING_MSG     DB      "       Working...","$"
  100. DONE_MSG        DB      "Done",CR,LF,"$"
  101. CRLF_MSG        DB      CR,LF,"$"
  102.  
  103. SRCCKSUM        DD      0                       ;dword for checksum
  104. ;
  105. ; Start of main code section
  106. ;
  107. START:          MOV     DX,OFFSET COPYRIGHT     ;copyright message
  108.                 MOV     AH,09H                  ;display string
  109.                 INT     21H                     ;dos interrupt
  110. ;
  111. ; Check and ensure that there is adequate memory
  112. ;
  113.                 CMP     SP,(OFFSET BUFFER-OFFSET CSEG+BYTES_LINE+STACKSAVE)
  114.                 JA      START1                  ;yes, lets continue
  115.                 MOV     AH,09H                  ;no, display message
  116.                 MOV     DX,OFFSET NOMEMORY      ;"not enough memory"
  117.                 INT     21H                     ;dos interrupt
  118.                 JMP     RETURN_TO_DOS           ;go end
  119.  
  120. START1:         CLD                             ;forward direction
  121.                 XOR     AX,AX                   ;clear ax
  122.                 MOV     AL,DS:[80H]             ;get parm count
  123.                 CMP     AL,1                    ;is it more than one?
  124.                 JA      GOTPARM                 ;yes, go handle
  125.                 JMP     HELP                    ;no, display usage and quit
  126. ;
  127. ; Remove blanks or tabs from the end of the filespec by replacing
  128. ; them with binary zero.  Skip leading spaces and tabs also.
  129. ;
  130. GOTPARM:        MOV     DI,AX                   ;use di
  131.                 INC     AX                      ;start with count+1
  132.                 MOV     CX,AX                   ;put in cx
  133. GOTPARM1:       MOV     BYTE PTR DS:[80H+DI+1],0  ;make asciiz
  134.                 DEC     CX                      ;decrement cx
  135.                 JNZ     GOTPARM3                ;not zero then continue
  136.                 JMP     HELP                    ;none left, give usage message
  137. GOTPARM3:       DEC     DI                      ;back up one
  138.                 CMP     BYTE PTR DS:[80H+DI+1]," "  ;is last byte a space?
  139.                 JE      GOTPARM1                ;yes, null it out
  140.                 CMP     BYTE PTR DS:[80H+DI+1],09H  ;is last byte a tab?
  141.                 JE      GOTPARM1                ;yes, null it out
  142. GOTPARM4:
  143.                 MOV     SI,80H                  ;set start
  144. GOTPARM5:
  145.                 INC     SI                      ;skip spaces and tabs
  146.                 CMP     BYTE PTR DS:[SI]," "    ;a space?
  147.                 JNE     GOTPARM6                ;no
  148.                 DEC     CX                      ;back it out
  149.                 JMP     GOTPARM5                ;yes
  150. GOTPARM6:
  151.                 CMP     BYTE PTR DS:[SI],09H    ;a tab?
  152.                 JNE     GOTPARM7                ;no
  153.                 DEC     CX                      ;back it out
  154.                 JMP     GOTPARM5                ;yes
  155. GOTPARM7:
  156.                 MOV     BYTE PTR DS:[80H],CL    ;store adjusted length
  157.                 MOV     FNSTART,SI              ;save start of filename
  158.                 CALL    STRUPPER                ;make uppercase
  159. ;
  160. ; If no file extent is present, use .COM as the default
  161. ;
  162. CHECKCOM:       MOV     CL,BYTE PTR DS:[80H]    ;get length
  163.                 MOV     DI,SI                   ;set start
  164.                 MOV     AL,"."                  ;look for start of extension
  165.                 REPNE   SCASB                   ;is it there?
  166.                 MOV     BX,DI                   ;save location in bx
  167.                 JNE     MAKECOM                 ;no extent, use default
  168.                 DEC     BX                      ;adjust to point to the "."
  169.                 JMP     SHORT OPENSRC           ;go open the file
  170.  
  171. MAKECOM:        MOV     CX,SRCFLEN              ;length of string
  172.                 MOV     SI,OFFSET SRCFILE       ;".COM,0"
  173.                 REP     MOVSB                   ;move in the default
  174. ;                                               ;extent (.COM)
  175. ; OPEN the source file for reading
  176. ;
  177. OPENSRC:        MOV     DX,FNSTART              ;get start of filename
  178.                 MOV     AX,3D00H                ;open for reading
  179.                 INT     21H                     ;dos interrupt
  180.                 JNC     OPENCOK                 ;no carry means success
  181.                 MOV     ERRORLVL,2              ;set errorlevel
  182.                 MOV     DX,OFFSET SRCERROR      ;error message
  183.                 MOV     AH,09H                  ;display string
  184.                 INT     21H                     ;dos interrupt
  185.                 JMP     RETURN_TO_DOS           ;carry means error
  186.  
  187. OPENCOK:        MOV     SRCHANDLE,AX            ;save handle
  188. ;
  189. ; Isolate the filename.ext portion of the pathspec
  190. ;
  191.                 MOV     DI,FNSTART              ;set for parsing
  192.                 CALL    FILENAME                ;look for filename.ext only
  193. ;
  194. ; Move the filename.ext into the appropriate places in the BASIC
  195. ; statements
  196. ;
  197. SAVNAME:        MOV     SI,DI                   ;get from position in si
  198.                 MOV     AX,SI                   ;save move from position in ax
  199.                 MOV     DX,CX                   ;save length in dx
  200.                 MOV     DI,OFFSET FLNAME        ;where to put filename
  201.                 REP     MOVSB                   ;move in flname
  202.                 MOV     SI,AX                   ;get back from position
  203.                 MOV     CX,DX                   ;get back length
  204.                 MOV     DI,OFFSET FLNAME0       ;where to put filename
  205.                 REP     MOVSB                   ;move in flname1
  206.                 MOV     SI,AX                   ;get back from position
  207.                 MOV     CX,DX                   ;get back length
  208.                 MOV     DI,OFFSET FLNAME1       ;where to put filename
  209.                 REP     MOVSB                   ;move in flname1
  210.                 MOV     SI,AX                   ;get back from position
  211.                 MOV     CX,DX                   ;get back length
  212.                 MOV     DI,OFFSET FLNAME2       ;where to put filename
  213.                 REP     MOVSB                   ;move in flname2
  214.                 MOV     SI,AX                   ;get back from position
  215.                 MOV     CX,DX                   ;get back length
  216.                 MOV     DI,OFFSET FLNAME3       ;where to put filename
  217.                 REP     MOVSB                   ;move in flname3
  218. ;
  219. ; Now change file extent to .BAS and try to open for writing.
  220. ; If this works, a .BAS file with the same name already exists
  221. ;
  222. MAKEBAS:        MOV     CX,BASFLEN              ;count in cx
  223.                 MOV     DI,BX                   ;restore position of extent
  224.                 MOV     SI,OFFSET BASFILE
  225.                 REP     MOVSB                   ;move in .bas extent
  226.                 XOR     BX,BX                   ;clear bx for later
  227.  
  228. OPENBAS:        MOV     DX,FNSTART              ;offset of filename
  229.                 MOV     AX,3D01H                ;open file for writing
  230.                 INT     21H                     ;dos interrupt
  231.                 JC      CREATEBAS               ;if this fails, go create file
  232.                 MOV     BASHANDLE,AX            ;save file handle
  233. ;
  234. ; If the .BAS file already exists, ask before overwriting
  235. ;
  236.                 MOV     DX,OFFSET EXISTSMSG     ;File exists, write over?
  237.                 MOV     AH,09H                  ;display string
  238.                 INT     21H                     ;dos interrupt
  239.  
  240. GETANS:         MOV     AX,0100H                ;DOS read kybd and echo
  241.                 INT     21H                     ;dos interrupt
  242.                 AND     AL,0DFH                 ;make uppercase
  243.                 OR      AL,AL                   ;is it extended key?
  244.                 JE      GETANS                  ;go get the keycode
  245.                 PUSH    AX                      ;save key
  246.                 MOV     DX,OFFSET CRLF_MSG      ;put out a CRLF combo
  247.                 MOV     AH,09H                  ;display string
  248.                 INT     21H                     ;dos interrupt
  249.                 POP     AX                      ;get back key
  250.                 CMP     AL,"Y"                  ;is it yes?
  251.                 JE      OVERWRITE               ;yes, continue
  252.                 JMP     CLOSFILES               ;no, go quit
  253. ;
  254. ; To overwrite the existing file, close it and then create it using
  255. ; function 3CH
  256. ;
  257. OVERWRITE:
  258.                 MOV     DX,OFFSET CRLF_MSG      ;put out a CRLF combo
  259.                 MOV     AH,09H                  ;display string
  260.                 INT     21H                     ;dos interrupt
  261.                 MOV     AX,3E00H                ;close file handle request
  262.                 MOV     BX,BASHANDLE            ;handle for .BAS file
  263.                 INT     21H                     ;close the file
  264. ;
  265. ; Create the .BAS file
  266. ;
  267. CREATEBAS:      MOV     DX,FNSTART              ;offset of filename
  268.                 XOR     CX,CX                   ;attribute normal
  269.                 MOV     AX,3C00H                ;create file
  270.                 INT     21H                     ;dos interrupt
  271.                 JNC     CREATOK                 ;no carry means success
  272.                 MOV     ERRORLVL,1              ;set errorlevel
  273.                 MOV     DX,OFFSET BASERROR      ;error message
  274.                 MOV     AH,09H                  ;display string
  275.                 INT     21H                     ;dos interrupt
  276.                 MOV     AX,3E00H                ;close file handle request
  277.                 MOV     BX,SRCHANDLE            ;close the source file
  278.                 INT     21H                     ;dos interrupt
  279.                 JMP     RETURN_TO_DOS           ;go end
  280.  
  281. CREATOK:        MOV     BASHANDLE,AX            ;save file handle
  282. ;
  283. ; Display "Working" message
  284. ;
  285.                 MOV     DX,OFFSET WORKING_MSG   ;"Working" message
  286.                 MOV     AH,09H                  ;display string
  287.                 INT     21H                     ;dos interrupt
  288. ;
  289. ; Calculate the number of DATA lines required
  290. ;
  291. NUMLINES:                                       ;Get the file size in bytes
  292.                 MOV     AX,4202H                ;move file pointer
  293.                 MOV     BX,SRCHANDLE            ;file handle for com file
  294.                 XOR     CX,CX                   ;seek to eof
  295.                 XOR     DX,DX                   ;clear
  296.                 INT     21H                     ;dos interrupt
  297.                 JNC     NUMLINES1               ;no carry means ok
  298.                 MOV     ERRORLVL,5              ;set errorlevel
  299.                 MOV     DX,OFFSET SRCERROR      ;error message
  300.                 JMP     ERROREXIT               ;carry means error
  301.  
  302. NUMLINES1:      XOR     BX,BX                   ;clear BX
  303.                 MOV     BL,BYTES_LINE           ;bytes per line
  304.                 DIV     BX                      ;calculate number of lines
  305.                 OR      DX,DX                   ;any remainder?
  306.                 JZ      NUMLINES2               ;no, go ahead
  307.                 INC     AX                      ;yes, one more line
  308. ;
  309. ; Convert values to ascii decimal and store in the BASIC statements
  310. ;
  311. NUMLINES2:      MOV     DI,OFFSET LINECOUNT     ;store no. 1f lines in ascii
  312.                 XOR     DX,DX                   ;high is zero, low in ax
  313.                 MOV     BX,10D                  ;decimal radix
  314.                 MOV     CX,5D                   ;width of output field
  315.                 CALL    BTOA                    ;convert to ascii
  316.  
  317.                 MOV     DI,OFFSET COUNTDOWN     ;store no. 1f lines in ascii
  318.                 MOV     CX,5D                   ;width of output field
  319.                 CALL    BTOA                    ;convert to ascii
  320.  
  321.                 MOV     DI,OFFSET B_PER_LINE    ;store bytes per line in ascii
  322.                 MOV     AX,BYTES_LINE           ;low is bytes per line
  323.                 MOV     CX,3D                   ;width of output field
  324.                 CALL    BTOA                    ;convert to ascii
  325.  
  326.                 MOV     DI,OFFSET ALASTBAS      ;store last line no. in ascii
  327.                 MOV     AX,LASTBASIC            ;low is bytes per line
  328.                 MOV     CX,5D                   ;width of output field
  329.                 CALL    BTOA                    ;convert to ascii
  330.  
  331.                 MOV     DI,OFFSET AINCR         ;store line increment
  332.                 XOR     AX,AX                   ;clear AX
  333.                 MOV     AL,LINE_INCR            ;low is bytes per line
  334.                 MOV     CX,3D                   ;width of output field
  335.                 CALL    BTOA                    ;convert to ascii
  336. ;
  337. ; Write everything except the DATA statements to the .BAS file
  338. ;
  339. WRITESOME:      MOV     DX,OFFSET BASIC_CODE    ;start of text
  340.                 MOV     CX,BASICLEN             ;length of write
  341.                 MOV     BX,BASHANDLE            ;handle for basic file
  342.                 CALL    WRITE_HANDLE            ;write to handle
  343.                 JNC     STARTDATA               ;no carry means ok
  344.                 MOV     ERRORLVL,4              ;set errorlevel
  345.                 MOV     DX,OFFSET BASERROR      ;error message
  346.                 JMP     ERROREXIT               ;carry means error
  347. ;
  348. ; Seek back to the beginning of the source file in order to create
  349. ; the DATA statements
  350. ;
  351. STARTDATA:      MOV     AX,4200H                ;move file pointer
  352.                 MOV     BX,SRCHANDLE            ;file handle for com file
  353.                 XOR     CX,CX                   ;seek to 0:0
  354.                 XOR     DX,DX
  355.                 INT     21H                     ;dos interrupt
  356.                 JNC     DATALOOP                ;no carry means ok
  357.                 MOV     ERRORLVL,5              ;set errorlevel
  358.                 MOV     DX,OFFSET SRCERROR      ;error message
  359.                 JMP     ERROREXIT               ;jump to error exit
  360. ;
  361. ; Create the DATA statements
  362. ;
  363. DATALOOP:       MOV     CX,BYTES_LINE           ;read BYTES_LINE bytes
  364.                 CALL    READDATA                ;read into the buffer
  365.                 JNC     DATALOOP1               ;no carry means ok
  366.                 MOV     ERRORLVL,3              ;set errorlevel
  367.                 MOV     DX,OFFSET SRCERROR      ;error message
  368.                 JMP     ERROREXIT               ;jump to error exit
  369.  
  370. DATALOOP1:      OR      AX,AX                   ;zero bytes read?
  371.                 JZ      FINISHED                ;yes, finished
  372.                 INC     LINENUMBER              ;increment line counter
  373.                 CALL    LINENUM                 ;put out line number
  374.                 JNC     DATALOOP2               ;no carry means ok
  375.                 MOV     ERRORLVL,6              ;set errorlevel
  376.                 MOV     DX,OFFSET LINERROR      ;error message
  377.                 JMP     ERROREXIT               ;jump to error exit
  378.  
  379. DATALOOP2:      MOV     CX,AX                   ;number of bytes from ax
  380.                 CALL    MAKEDATA                ;go make data statement
  381.  
  382.                 MOV     CX,BASICDATAL           ;length of write
  383.                 CALL    WRITEDATA               ;write out data statement
  384.                 JNC     DATALOOP                ;go do some more
  385.                 MOV     ERRORLVL,4              ;set errorlevel
  386.                 MOV     DX,OFFSET BASERROR      ;error message
  387.                 JMP     ERROREXIT               ;jump to error exit
  388. ;
  389. ; Convert the checksum to decimal ascii and store in the final data
  390. ; statement
  391. ;
  392. FINISHED:       INC     LINENUMBER              ;increment line counter
  393.                 CALL    LINENUM                 ;put out line number
  394.  
  395.                 MOV     DI,OFFSET BBUFFER       ;store byte sum in ascii
  396.                 PUSH    DI                      ;save a moment
  397.                 MOV     DX,WORD PTR SRCCKSUM+2
  398.                 MOV     AX,WORD PTR SRCCKSUM    ;low in ax, high in dx
  399.                 MOV     BX,10D                  ;decimal radix
  400.                 MOV     CX,11D                  ;width of output field
  401.                 CALL    BTOA                    ;convert to ascii
  402.                 MOV     SI,DI                   ;get address in si
  403.                 POP     DI                      ;restore buffer address
  404.                 REP     MOVSB                   ;move flush left
  405.                 MOV     AL,CR                   ;end of line
  406.                 STOSB                           ;store the byte
  407.                 MOV     AL,LF                   ;end of line
  408.                 STOSB                           ;store the byte
  409.                 MOV     CX,DI                   ;position in cx
  410.                 SUB     CX,OFFSET BASICDATA     ;calculate length
  411. FINISHED2:
  412.                 CALL    WRITEDATA               ;write out data statement
  413.                 JNC     DISPDONE                ;go do some more
  414.                 MOV     ERRORLVL,4              ;set errorlevel
  415.                 MOV     DX,OFFSET BASERROR      ;error message
  416.                 JMP     ERROREXIT               ;jump to error exit
  417. ;
  418. ; Display "Done" message
  419. ;
  420. DISPDONE:
  421.                 MOV     AH,09H                  ;display message
  422.                 MOV     DX,OFFSET DONE_MSG      ;"Done" message
  423.                 INT     21H                     ;dos interrupt
  424. ;
  425. ; Close both files
  426. ;
  427. CLOSFILES:
  428.                 MOV     AX,3E00H                ;close file handle request
  429.                 MOV     BX,SRCHANDLE            ;close the source file
  430.                 INT     21H                     ;dos interrupt
  431.                 MOV     AX,3E00H                ;close file handle request
  432.                 MOV     BX,BASHANDLE            ;close the source file
  433.                 INT     21H                     ;dos interrupt
  434. ;
  435. ; Set errorlevel and return to dos
  436. ;
  437. RETURN_TO_DOS:
  438.                 MOV     AH,04CH                 ;terminate process
  439.                 MOV     AL,ERRORLVL             ;get return code
  440.                 INT     21H                     ;return to dos
  441. ;
  442. ; Error exit - display message, close files and terminate
  443. ;
  444. ERROREXIT:
  445.                 MOV     AH,09H                  ;display string
  446.                 INT     21H                     ;dos interrupt
  447.                 JMP     CLOSFILES               ;go close and end
  448.  
  449. HELP:           MOV     DX,OFFSET USAGE         ;usage message
  450.                 MOV     AH,09H                  ;display string
  451.                 INT     21H                     ;dos interrupt
  452.                 JMP     RETURN_TO_DOS
  453.  
  454. ;----------------------------------------------------------------------
  455. ; WRITEDATA -  Write out a data statement.  Entry: CX has bytecount.
  456. ; This routine removes leading blanks from the linenumbers.
  457. ;----------------------------------------------------------------------
  458. WRITEDATA       PROC    NEAR
  459.                 MOV     SI,OFFSET BASICDATA     ;start of data statement
  460. ;
  461. ; Scan past leading blanks...
  462. ;
  463. WRITED001:      CMP     BYTE PTR DS:[SI]," "    ;is it a blank?
  464.                 JNE     WRITED002               ;no, go write
  465.                 INC     SI                      ;skip the blank
  466.                 DEC     CX                      ;count - 1
  467.                 JMP     WRITED001               ;check next char
  468.  
  469. WRITED002:      MOV     DX,SI                   ;start position in DX
  470.                 MOV     BX,BASHANDLE            ;handle for basic file
  471.                 CALL    WRITE_HANDLE            ;write to handle
  472.                 RET
  473. WRITEDATA       ENDP
  474.  
  475. ;----------------------------------------------------------------------
  476. ; LINESUM - Convert line sum to ascii decimal and put in data
  477. ; statement followed by CR,LF.   Entry: Line sum in BX
  478. ;----------------------------------------------------------------------
  479. LINESUM         PROC    NEAR                    ;create line checksum
  480.                 ASSUME  CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  481.                 PUSH    DI                      ;save di
  482.                 MOV     CX,5                    ;blank fill first
  483.                 MOV     AL," "
  484.                 REP     STOSB
  485.                 POP     DI                      ;restore di
  486.                 XOR     DX,DX                   ;high is zero
  487.                 MOV     AX,BX                   ;low is line sum
  488.                 OR      AX,AX                   ;is it zero?
  489.                 JNZ     LINESUM1                ;no, continue
  490.  
  491.                 MOV     AX,"  "                 ;lead with blanks
  492.                 STOSW
  493.                 STOSB
  494.                 MOV     AX,"0 "                 ;put out zero
  495.                 STOSW
  496.                 JMP     SHORT LINESUM2
  497.  
  498. LINESUM1:       ADD     WORD PTR SRCCKSUM,AX    ;add to the
  499.                 ADC     WORD PTR SRCCKSUM+2,DX  ;file checksum
  500.                 PUSH    DI                      ;save it again
  501.                 MOV     BX,16D                  ;hexadecimal radix
  502.                 MOV     CX,5D                   ;width of buffer
  503.                 CALL    BTOA                    ;go convert to ascii
  504.                 POP     DI                      ;get it back
  505.  
  506.                 ADD     DI,5                    ;point past line sum
  507. LINESUM2:       MOV     AL,CR                   ;end of line
  508.                 STOSB                           ;store the byte
  509.                 MOV     AL,LF                   ;end of line
  510.                 STOSB                           ;store the byte
  511.  
  512.                 RET
  513. LINESUM         ENDP
  514.  
  515. ;----------------------------------------------------------------------
  516. ; READDATA - Reads CX bytes from source file into buffer.
  517. ; Exit: AX contains number of bytes read
  518. ;       If error occurred, carry set and AX contains error code
  519. ;----------------------------------------------------------------------
  520. READDATA        PROC    NEAR                    ;read BYTES_LINE bytes
  521.                 ASSUME  CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  522.                 PUSH    BX                      ;save registers
  523.                 PUSH    DX
  524.                 MOV     AX,3F00H                ;read from file handle
  525.                 MOV     BX,SRCHANDLE            ;handle for COM file
  526.                 MOV     DX,OFFSET BUFFER        ;address of buffer
  527.                 INT     21H                     ;get em from dos
  528.                 POP     DX                      ;restore registers
  529.                 POP     BX
  530.                 RET
  531. READDATA        ENDP
  532.  
  533. ;----------------------------------------------------------------------
  534. ; WRITE_HANDLE - Write to file handle.
  535. ; Input: DS:DX addresses buffer.  CX has bytecount.
  536. ;        BX has file handle.
  537. ; Exit:  AX has count written unless carry is set, in which case
  538. ;        an error code is in AX.
  539. ;----------------------------------------------------------------------
  540. WRITE_HANDLE    PROC    NEAR                    ;write to file handle
  541.                 ASSUME  CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  542.                 PUSH    CX                      ;save just in case
  543.                 MOV     AH,40H                  ;write to handle function
  544.                 INT     21H                     ;dos interrupt
  545.                 POP     CX                      ;get back cx
  546.                 JC      WRITE_HRET              ;carry set, return immediately
  547.                 CMP     AX,CX                   ;did we write them all?
  548.                 JE      WRITE_HRET              ;yes, go return
  549.                 STC                             ;no, set carry
  550. WRITE_HRET:
  551.                 RET
  552. WRITE_HANDLE    ENDP
  553.  
  554. ;----------------------------------------------------------------------
  555. ; MAKEDATA - Creates a BASIC data statement containing the next CX
  556. ; bytes in hexadecimal, followed by a line sum.
  557. ; Entry: CX - byte count.
  558. ;----------------------------------------------------------------------
  559. MAKEDATA        PROC    NEAR                    ;make a basic data statement
  560.                 ASSUME  CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  561.                 MOV     BP,CX                   ;save byte count in bp
  562.                 MOV     DI,OFFSET BBUFFER       ;start of ascii buffer
  563.                 MOV     SI,OFFSET BUFFER        ;start of data buffer
  564.                 XOR     AX,AX                   ;start with clear ax
  565.                 XOR     BX,BX                   ;sixteen byte sum in bx
  566.  
  567. MAKE00010:      LODSB                           ;get byte in AL
  568.                 ADD     BX,AX                   ;add to sum
  569.                 CALL    PUTHEX                  ;put out al in hex
  570.                 MOV     AX," ,"                 ;need a comma and space
  571.                 STOSW                           ;store the byte
  572.                 XOR     AH,AH                   ;clear AH
  573.                 LOOP    MAKE00010               ;loop
  574.  
  575.                 CMP     BP,BYTES_LINE           ;was this a complete line
  576.                 JE      MAKE01000               ;yes, then go finish up
  577.  
  578.                 MOV     CX,BYTES_LINE           ;calculate padding
  579.                 SUB     CX,BP                   ;requirement
  580. MAKE00200:      MOV     AX,"0 "                 ;pad with zeros
  581.                 STOSW                           ;move them in
  582.                 MOV     AX," ,"                 ;comma and space
  583.                 STOSW                           ;move it in
  584.                 LOOP    MAKE00200               ;continue until finished
  585.  
  586. MAKE01000:      CALL    LINESUM                 ;convert and put out linesum
  587.                                                 ;and cr,lf
  588.                 RET
  589. MAKEDATA        ENDP
  590.  
  591. ;----------------------------------------------------------------------
  592. ; PUTHEX - Output AL in hexadecimal to ES:DI.  Replace a leading zero
  593. ;          with a space
  594. ;----------------------------------------------------------------------
  595. PUTHEX          PROC    NEAR                    ;output al in hex to es:di
  596.                 ASSUME  CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  597.                 PUSH    AX                      ;save a moment
  598.                 SHR     AL,1                    ;isolate high nibble
  599.                 SHR     AL,1
  600.                 SHR     AL,1
  601.                 SHR     AL,1
  602.                 JZ      PUTHEX1                 ;jump if zero
  603.                 ADD     AL,90H                  ;convert al
  604.                 DAA                             ;to hex
  605.                 ADC     AL,40H
  606.                 DAA
  607.                 STOSB                           ;store the byte
  608.                 JMP     PUTHEX2
  609. PUTHEX1:        MOV     AL," "                  ;zero suppress
  610.                 STOSB                           ;store the byte
  611. PUTHEX2:        POP     AX                      ;get back original
  612.                 AND     AL,0FH                  ;isolate low nibble
  613.                 ADD     AL,90H                  ;convert al
  614.                 DAA                             ;to hex
  615.                 ADC     AL,40H
  616.                 DAA
  617.                 STOSB                           ;store the byte
  618.                 RET
  619. PUTHEX          ENDP
  620.  
  621. ;----------------------------------------------------------------------
  622. ; LINENUM - Calculate a new line number for the data statement and
  623. ; move it in.   Exit: Carry set if too many lines
  624. ;----------------------------------------------------------------------
  625. LINENUM         PROC    NEAR                    ;create line number
  626.                 ASSUME  CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  627.                 PUSH    AX                      ;save ax
  628.                 PUSH    DI                      ;save di
  629.                 PUSH    CX                      ;and cx
  630.                 CLC                             ;clear carry
  631.                 MOV     CX,LINENUMBER           ;get current line number
  632.                 XOR     DX,DX                   ;high is zero
  633.                 MOV     AX,LINE_INCR            ;multiply by line increment
  634.                 MUL     CX
  635.                 JC      LINENUME                ;carry means too many
  636.                 ADD     AX,LASTBASIC            ;add last basic statement no.
  637.                 JC      LINENUME                ;carry means too many
  638.                 MOV     DI,OFFSET BASICDATA     ;where to put lineno
  639.                 XOR     DX,DX                   ;clear high word, low is in ax
  640.                 MOV     BX,10D                  ;radix is decimal
  641.                 MOV     CX,5D                   ;width of field
  642.                 CALL    BTOA                    ;convert to ascii
  643.                 CLC                             ;make sure carry is clear
  644. LINENUME:       POP     CX                      ;restore cx
  645.                 POP     DI                      ;restore di
  646.                 POP     AX                      ;restore ax
  647.                 RET
  648. LINENUM         ENDP
  649.  
  650. ;----------------------------------------------------------------------
  651. ; FILENAME - Find filename.ext in a full path specification.
  652. ; Entry: ES:DI points to asciiz full path specification.
  653. ; Exit: ES:DI points to the name.ext only.
  654. ;       CX contains the length of the name.ext in bytes.
  655. ;       Carry flag set if error occurs (ES:DI, CX not valid).
  656. ;----------------------------------------------------------------------
  657. FILENAME        PROC    NEAR                    ;find the name and extent
  658.                 ASSUME  CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  659.                 PUSH    AX                      ;save AX
  660.                 XOR     AX,AX                   ;zero out AX
  661.                 MOV     CX,0FFFFH               ;maximum search
  662.                 CLD                             ;set direction forward
  663.                 REPNE   SCASB                   ;look for the terminating null
  664.                 JNE     FILENAME7               ;error if not found
  665.  
  666.                 DEC     DI                      ;adjust DI to point to last
  667.                 DEC     DI                      ;character
  668.                 NOT     CX                      ;get length in CX
  669.                 DEC     CX                      ;adjust the length
  670.                 XOR     AX,AX                   ;clear ax again
  671.                 PUSH    CX                      ;save CX temporarily
  672.                 STD                             ;reverse the direction
  673.                 MOV     AL,"\"                  ;path seperator
  674.                 REPNE   SCASB                   ;look for the \
  675.                 JNE     FILENAME1               ;no \ found
  676.  
  677.                 INC     DI                      ;adjust DI
  678.                 INC     DI
  679.                 POP     AX                      ;get search length in AX
  680.                 SUB     AX,CX                   ;back out CX
  681.                 MOV     CX,AX                   ;get length in CX
  682.                 DEC     CX                      ;adjust the length
  683.                 JMP     SHORT FILENAME9         ;go return
  684.  
  685. FILENAME1:      INC     DI                      ;adjust DI
  686.                 POP     CX                      ;get search length in CX
  687.                 CMP     CX,12D                  ;longer than 12 bytes?
  688.                 JLE     FILENAME9               ;no, ok
  689.  
  690. FILENAME7:      STC                             ;set carry to indicate error
  691.  
  692. FILENAME9:      CLD                             ;set direction forward
  693.                 POP     AX                      ;restore AX
  694.                 RET                             ;return to caller
  695. FILENAME        ENDP
  696.  
  697. ;----------------------------------------------------------------------
  698. ; BTOA - Unsigned binary to ascii conversion.
  699. ; Entry: DX:AX contains value to convert. ES:DI addresses the output
  700. ; buffer.  BX contains radix (eg. 10d is decimal, 16d is hexadecimal).
  701. ; CX contains the size of the output buffer in bytes.
  702. ; Exit: ES:DI address the result.  CX contains length in bytes.
  703. ;----------------------------------------------------------------------
  704. BTOA            PROC    NEAR                    ;unsigned binary to ascii conv
  705.                 ASSUME  CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  706.                 PUSH    DX                      ;save DX
  707.                 PUSH    AX                      ;and AX
  708.                 PUSH    AX                      ;save AX for as moment
  709.                 MOV     AL," "                  ;first blank fill
  710.                 REP     STOSB                   ;the buffer
  711.                 POP     AX                      ;get back AX
  712.                 DEC     DI                      ;start at the last position
  713.                 PUSH    DI                      ;save start address
  714.  
  715. BTOA0010:       MOV     CX,DX                   ;get high in cx
  716.                 OR      CX,AX                   ;is value zero?
  717.                 JZ      BTOA9900                ;yes, jump out
  718.  
  719. BTOA0020:       PUSH    AX                      ;save ax
  720.                 MOV     AX,DX
  721.                 XOR     DX,DX                   ;0:div-high/divisor
  722.                 DIV     BX
  723.                 MOV     CX,AX                   ;save quotient in cx
  724.                 POP     AX                      ;restore ax
  725.                 DIV     BX                      ;remainder:div-low/divisor
  726.                 XCHG    CX,DX                   ;get first quotient in dx
  727.                                                 ;dx:ax=quotient, cx=remainder
  728.                 ADD     CL,"0"                  ;make ascii
  729.                 CMP     CL,"9"                  ;greater than 9 needs hex
  730.                 JBE     BTOA1000                ;no, less than 9
  731.                 ADD     CL,'A'-'9'-1            ;map to uppercase hex
  732.  
  733. BTOA1000:       MOV     ES:[DI],CL              ;store it
  734.                 DEC     DI                      ;decrement destination
  735.                 MOV     CX,DX                   ;get high in cx
  736.                 OR      CX,AX                   ;is value zero?
  737.                 JZ      BTOA9900                ;yes, jump out
  738.                 JMP     BTOA0020                ;loop
  739.  
  740. BTOA9900:       POP     CX                      ;original address
  741.                 SUB     CX,DI                   ;back out current address
  742.                 INC     DI                      ;point to start
  743.                 POP     AX                      ;restore dx:ax
  744.                 POP     DX
  745.                 RET
  746. BTOA            ENDP
  747.  
  748. ;----------------------------------------------------------------------
  749. ; STRUPPER - Convert asciiz string to uppercase.
  750. ; Entry: DS:SI addresses the string. String must end with binary 0.
  751. ;----------------------------------------------------------------------
  752. STRUPPER        PROC    NEAR                    ;uppercase asciiz string
  753.                 ASSUME  CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  754.                 PUSH    AX                      ;save ax
  755.                 PUSH    SI                      ;save di
  756. STRUPPER1:
  757.                 LODSB                           ;get char in al
  758.                 OR      AL,AL                   ;is it zero
  759.                 JZ      STRUPPER2               ;yes, we are finished
  760.                 CMP     AL,'a'                  ;less than 'a'
  761.                 JB      STRUPPER1               ;yes, skip it
  762.                 CMP     AL,'z'                  ;above 'z'
  763.                 JA      STRUPPER1               ;yes, skip it
  764.                 AND     AL,0DFH                 ;mask bit 5, make uppercase
  765.                 MOV     BYTE PTR DS:[SI-1],AL   ;replace
  766.                 JMP     STRUPPER1               ;loop and get another
  767. STRUPPER2:
  768.                 POP     SI                      ;restore di
  769.                 POP     AX                      ;restore ax
  770.                 RET
  771. STRUPPER        ENDP
  772.  
  773. BUFFER          LABEL   BYTE                    ;Storage for i/o buffer
  774.  
  775. CSEG            ENDS
  776.                 END     ENTRY
  777.